﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Windows.Forms;
using GemBox.Spreadsheet;
using LicenseKey;
using MetadataDocumentationGenerator.Helpers;
using MetadataDocumentationGenerator.Properties;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Metadata;

namespace MetadataDocumentationGenerator.Generator
{
    internal class ExcelDocument2 : IDocument2
    {
        private int _index;

        #region Variables

        /// <summary>
        /// Excel workbook
        /// </summary>
        readonly ExcelFile _innerWorkBook;

        /// <summary>
        /// Generation Settings
        /// </summary>
        readonly GenerationSettings _settings;

        /// <summary>
        /// Line number where to write
        /// </summary>
        int _lineNumber;

        /// <summary>
        /// Indicates if the header row of attributes for the current entity
        /// is already added
        /// </summary>
        bool _attributesHeaderAdded;

        bool _entitiesHeaderAdded;

        #endregion Variables

        #region Constructor

        /// <summary>
        /// Initializes a new instance of class ExcelDocument
        /// </summary>
        /// <param name="generationSettings">Settings for generation</param>
        public ExcelDocument2(GenerationSettings generationSettings)
        {
            var key = new Key();
            SpreadsheetInfo.SetLicense(key.ExcelLicenseKey);

            _innerWorkBook = new ExcelFile();
            _settings = generationSettings;
            _lineNumber = 0;
        }

        #endregion Constructor

        #region Properties
        
        public string Filter
        {
            get { return Resources.ExcelFilter; }
        }

        public bool IsMultipleOutput
        {
            get { return false; }
        }

        #endregion

        public void Generate(Action<GenerationProgress> triggerProgressChanged, IOrganizationService service , List<EntityMetadata> entityList)
        {
            _index = 0;

            if (_settings.AddEntitiesSummary)
            {
                _lineNumber = 1;

                var sheet = AddWorkSheet("Entities list");
                sheet.Cells[_lineNumber, 0].Value = Resources.GeneratedOn;
                sheet.Cells[_lineNumber, 1].Value = DateTime.Now.ToString(CultureInfo.InvariantCulture);
                _lineNumber++;

                sheet.Cells[_lineNumber, 0].Value = AssemblyHelper.GetAssemblyTitle() + " v." +
                                                    Application.ProductVersion.ToString(CultureInfo.InvariantCulture);
                _lineNumber++;

                foreach (var emd in _settings.EntitiesToProceed)
                {
                    AddEntityMetadataInLine(entityList.First(x => x.LogicalName == emd.Name), sheet);
                }
            }

            foreach (var entity in _settings.EntitiesToProceed)
            {
                var emd = entityList.First(x => x.LogicalName == entity.Name);

                var gp = new GenerationProgress
                {
                    CurrentEntity = entity.Name,
                    CurrentStep = _index,
                    TotalSteps = _settings.EntitiesToProceed.Count
                };

                _lineNumber = 1;

                var displayNameLabel =
                    emd.DisplayName.LocalizedLabels.FirstOrDefault(
                        l => l.LanguageCode == _settings.DisplayNamesLangugageCode);

                string name = string.Format("{0} ({1})",
                                            displayNameLabel == null ? "N/A" : displayNameLabel.Label,
                                            emd.SchemaName);

                triggerProgressChanged(gp);

                var sheet = AddWorkSheet(name);

                if (!_settings.AddEntitiesSummary)
                {
                    AddEntityMetadata(emd, sheet);
                }

                var formsDoc = MetadataHelper.RetrieveEntityForms(emd.LogicalName, service);

                IEnumerable<AttributeMetadata> amds = new List<AttributeMetadata>();

                switch (_settings.AttributesSelection)
                {
                    case AttributeSelectionOption.AllAttributes:
                        amds = emd.Attributes;
                        break;
                    case AttributeSelectionOption.AttributesOptionSet:
                        amds = emd.Attributes.Where(x => x.AttributeType != null && (x.AttributeType.Value == AttributeTypeCode.Boolean
                                                                                     || x.AttributeType.Value == AttributeTypeCode.Picklist
                                                                                     || x.AttributeType.Value == AttributeTypeCode.State
                                                                                     || x.AttributeType.Value == AttributeTypeCode.Status));
                        break;
                    case AttributeSelectionOption.AttributeManualySelected:
                        amds =
                            emd.Attributes.Where(
                                x =>
                                _settings.EntitiesToProceed.First(y => y.Name == emd.LogicalName).Attributes.Contains(
                                    x.LogicalName));
                        break;
                    case AttributeSelectionOption.AttributesOnForm:
                        amds =
                            emd.Attributes.Where(
                                x =>
                                formsDoc.SelectSingleNode("//control[@datafieldname='" + x.LogicalName + "']") != null);
                        break;
                }

                if (amds.Any())
                {
                    foreach (var amd in amds)
                    {
                        AddAttribute(emd.Attributes.First(x => x.LogicalName == amd.LogicalName), sheet);
                    }
                }
                else
                {
                    Write("no attributes to display", sheet, 1, !_settings.AddEntitiesSummary ? 10 : 1);
                }

                triggerProgressChanged(gp);
                _index++;
            }
        }

        #region Methods

        /// <summary>
        /// Add a new worksheet
        /// </summary>
        /// <param name="sheetName">Name of the worksheet</param>
        /// <returns></returns>
        public ExcelWorksheet AddWorkSheet(string sheetName)
        {
           
            sheetName = sheetName
                .Replace(":", " ")
                .Replace("\\", " ")
                .Replace("/", " ")
                .Replace("?", " ")
                .Replace("*", " ")
                .Replace("[", " ")
                .Replace("]", " ");

            if (sheetName.Length > 31)
                sheetName = sheetName.Substring(0, 31);

            _lineNumber = 1;
            _attributesHeaderAdded = false;

            return _innerWorkBook.Worksheets.Add(sheetName);
        }

        /// <summary>
        /// Adds metadata of an entity
        /// </summary>
        /// <param name="emd">Entity metadata</param>
        /// <param name="sheet">Worksheet where to write</param>
        public void AddEntityMetadata(EntityMetadata emd, ExcelWorksheet sheet)
        {
            _attributesHeaderAdded = false;
            _lineNumber = 0;

            sheet.Cells[_lineNumber, 0].Value = "Entity";
            sheet.Cells[_lineNumber, 0].Style.FillPattern.SetSolid(Color.PowderBlue);
            sheet.Cells[_lineNumber, 0].Style.Font.Weight = ExcelFont.BoldWeight;
            sheet.Cells[_lineNumber, 1].Value = emd.DisplayName.LocalizedLabels.Count == 0 ? emd.SchemaName : emd.DisplayName.LocalizedLabels.First(l => l.LanguageCode == _settings.DisplayNamesLangugageCode).Label;
            _lineNumber++;

            sheet.Cells[_lineNumber, 0].Value = ("Plural Display Name");
            sheet.Cells[_lineNumber, 0].Style.FillPattern.SetSolid(Color.PowderBlue);
            sheet.Cells[_lineNumber, 0].Style.Font.Weight = ExcelFont.BoldWeight;
            sheet.Cells[_lineNumber, 1].Value = (emd.DisplayCollectionName.LocalizedLabels.Count == 0 ? "N/A" : emd.DisplayCollectionName.LocalizedLabels.First(l => l.LanguageCode == _settings.DisplayNamesLangugageCode).Label);
            _lineNumber++;

            sheet.Cells[_lineNumber, 0].Value = ("Description");
            sheet.Cells[_lineNumber, 0].Style.FillPattern.SetSolid(Color.PowderBlue);
            sheet.Cells[_lineNumber, 0].Style.Font.Weight = ExcelFont.BoldWeight;
            sheet.Cells[_lineNumber, 1].Value = (emd.Description.LocalizedLabels.Count == 0 ? "N/A" : emd.Description.LocalizedLabels.First(l => l.LanguageCode == _settings.DisplayNamesLangugageCode).Label);
            _lineNumber++;

            sheet.Cells[_lineNumber, 0].Value = ("Schema Name");
            sheet.Cells[_lineNumber, 0].Style.FillPattern.SetSolid(Color.PowderBlue);
            sheet.Cells[_lineNumber, 0].Style.Font.Weight = ExcelFont.BoldWeight;
            sheet.Cells[_lineNumber, 1].Value = (emd.SchemaName);
            _lineNumber++;

            sheet.Cells[_lineNumber, 0].Value = ("Logical Name");
            sheet.Cells[_lineNumber, 0].Style.FillPattern.SetSolid(Color.PowderBlue);
            sheet.Cells[_lineNumber, 0].Style.Font.Weight = ExcelFont.BoldWeight;
            sheet.Cells[_lineNumber, 1].Value = (emd.LogicalName);
            _lineNumber++;

            sheet.Cells[_lineNumber, 0].Value = ("Object Type Code");
            sheet.Cells[_lineNumber, 0].Style.FillPattern.SetSolid(Color.PowderBlue);
            sheet.Cells[_lineNumber, 0].Style.Font.Weight = ExcelFont.BoldWeight;
            sheet.Cells[_lineNumber, 1].Style.HorizontalAlignment = HorizontalAlignmentStyle.Left;
            if (emd.ObjectTypeCode != null) sheet.Cells[_lineNumber, 1].Value = (emd.ObjectTypeCode.Value);
            _lineNumber++;

            sheet.Cells[_lineNumber, 0].Value = ("Is Custom Entity");
            sheet.Cells[_lineNumber, 0].Style.FillPattern.SetSolid(Color.PowderBlue);
            sheet.Cells[_lineNumber, 0].Style.Font.Weight = ExcelFont.BoldWeight;
            sheet.Cells[_lineNumber, 1].Value = (emd.IsCustomEntity != null && emd.IsCustomEntity.Value).ToString(CultureInfo.GetCultureInfo(_settings.DisplayNamesLangugageCode));
            sheet.Cells[_lineNumber, 1].Style.HorizontalAlignment = HorizontalAlignmentStyle.Left;
            _lineNumber++;

            sheet.Cells[_lineNumber, 0].Value = ("Ownership Type");
            sheet.Cells[_lineNumber, 0].Style.FillPattern.SetSolid(Color.PowderBlue);
            sheet.Cells[_lineNumber, 0].Style.Font.Weight = ExcelFont.BoldWeight;
            if (emd.OwnershipType != null) sheet.Cells[_lineNumber, 1].Value = (emd.OwnershipType.Value);
            _lineNumber++;
            _lineNumber++;
        }

        /// <summary>
        /// Add an attribute metadata
        /// </summary>
        /// <param name="amd">Attribute metadata</param>
        /// <param name="sheet">Worksheet where to write</param>
        public void AddAttribute(AttributeMetadata amd, ExcelWorksheet sheet)
        {
            var y = 0;

            if (!_attributesHeaderAdded)
            {
                InsertAttributeHeader(sheet, _lineNumber, y);
                _attributesHeaderAdded = true;
            }
            _lineNumber++;

            sheet.Cells[_lineNumber, y].Value = (amd.LogicalName);
            y++;

            sheet.Cells[_lineNumber, y].Value = (amd.SchemaName);
            y++;

            sheet.Cells[_lineNumber, y].Value = (amd.DisplayName.LocalizedLabels.Count == 0 ? "N/A" : amd.DisplayName.LocalizedLabels.First(l => l.LanguageCode == _settings.DisplayNamesLangugageCode).Label);
            y++;

            if (amd.AttributeType != null) sheet.Cells[_lineNumber, y].Value = (amd.AttributeType.Value.ToString());
            y++;

            sheet.Cells[_lineNumber, y].Value = (amd.Description.LocalizedLabels.Count == 0 ? "N/A" : amd.Description.LocalizedLabels.First(l => l.LanguageCode == _settings.DisplayNamesLangugageCode).Label);
            y++;

            sheet.Cells[_lineNumber, y].Value = ((amd.IsCustomAttribute != null && amd.IsCustomAttribute.Value).ToString(CultureInfo.InvariantCulture));
            y++;

            if (_settings.AddRequiredLevelInformation)
            {
                sheet.Cells[_lineNumber, y].Value = (amd.RequiredLevel.Value.ToString());
                y++;
            }

            if (_settings.AddValidForAdvancedFind)
            {
                sheet.Cells[_lineNumber, y].Value = (amd.IsValidForAdvancedFind.Value.ToString(CultureInfo.InvariantCulture));
                y++;
            }

            if (_settings.AddAuditInformation)
            {
                sheet.Cells[_lineNumber, y].Value = (amd.IsAuditEnabled.Value.ToString(CultureInfo.InvariantCulture));
                y++;
            }

            if (_settings.AddFieldSecureInformation)
            {
                sheet.Cells[_lineNumber, y].Value = ((amd.IsSecured != null && amd.IsSecured.Value).ToString(CultureInfo.InvariantCulture));
                y++;
            }

            AddAdditionalData(_lineNumber, y, amd, sheet);
        }

        /// <summary>
        /// Saves the current workbook
        /// </summary>
        /// <param name="path">Path where to save the document</param>
        public void SaveDocument(string path)
        {
            _innerWorkBook.SaveXlsx(path);
        }

        /// <summary>
        /// Adds attribute type specific metadata information
        /// </summary>
        /// <param name="x">Row number</param>
        /// <param name="y">Cell number</param>
        /// <param name="amd">Attribute metadata</param>
        /// <param name="sheet">Worksheet where to write</param>
        private void AddAdditionalData(int x, int y, AttributeMetadata amd, ExcelWorksheet sheet)
        {
            if (amd.AttributeType != null)
                switch (amd.AttributeType.Value)
                {
                    case AttributeTypeCode.BigInt:
                        {
                            var bamd = (BigIntAttributeMetadata)amd;

                            sheet.Cells[x,y].Value = (string.Format(
                                "Minimum value: {0}\r\nMaximum value: {1}",
                                bamd.MinValue.HasValue ? bamd.MinValue.Value.ToString(CultureInfo.InvariantCulture) : "N/A",
                                bamd.MaxValue.HasValue ? bamd.MaxValue.Value.ToString(CultureInfo.InvariantCulture) : "N/A"));
                        }
                        break;
                    case AttributeTypeCode.Boolean:
                        {
                            var bamd = (BooleanAttributeMetadata)amd;

                            sheet.Cells[x, y].Value = (string.Format(
                                "True: {0}\r\nFalse: {1}\r\nDefault Value: {2}",
                                bamd.OptionSet.TrueOption.Label.LocalizedLabels.First(l => l.LanguageCode == _settings.DisplayNamesLangugageCode).Label,
                                bamd.OptionSet.FalseOption.Label.LocalizedLabels.First(l => l.LanguageCode == _settings.DisplayNamesLangugageCode).Label,
                                bamd.DefaultValue.HasValue ? bamd.DefaultValue.Value.ToString(CultureInfo.InvariantCulture) : "N/A"));
                        }
                        break;
                    case AttributeTypeCode.Customer:
                        {
                            // Do Nothing
                        }
                        break;
                    case AttributeTypeCode.DateTime:
                        {
                            var damd = (DateTimeAttributeMetadata)amd;

                            sheet.Cells[x, y].Value = (string.Format(
                                "Format: {0}",
                                damd.Format.HasValue ? damd.Format.Value.ToString() : "N/A"));
                        }
                        break;
                    case AttributeTypeCode.Decimal:
                        {
                            var damd = (DecimalAttributeMetadata)amd;

                            sheet.Cells[x, y].Value = (string.Format(
                                "Minimum value: {0}\r\nMaximum value: {1}\r\nPrecision: {2}",
                                damd.MinValue.HasValue ? damd.MinValue.Value.ToString(CultureInfo.InvariantCulture) : "N/A",
                                damd.MaxValue.HasValue ? damd.MaxValue.Value.ToString(CultureInfo.InvariantCulture) : "N/A",
                                damd.Precision.HasValue ? damd.Precision.Value.ToString(CultureInfo.InvariantCulture) : "N/A"));
                        }
                        break;
                    case AttributeTypeCode.Double:
                        {
                            var damd = (DoubleAttributeMetadata)amd;

                            sheet.Cells[x, y].Value = (string.Format(
                                "Minimum value: {0}\r\nMaximum value: {1}\r\nPrecision: {2}",
                                damd.MinValue.HasValue ? damd.MinValue.Value.ToString(CultureInfo.InvariantCulture) : "N/A",
                                damd.MaxValue.HasValue ? damd.MaxValue.Value.ToString(CultureInfo.InvariantCulture) : "N/A",
                                damd.Precision.HasValue ? damd.Precision.Value.ToString(CultureInfo.InvariantCulture) : "N/A"));
                        }
                        break;
                    case AttributeTypeCode.EntityName:
                        {
                            // Do nothing
                        }
                        break;
                    case AttributeTypeCode.Integer:
                        {
                            var iamd = (IntegerAttributeMetadata)amd;

                            sheet.Cells[x, y].Value = (string.Format(
                                "Minimum value: {0}\r\nMaximum value: {1}",
                                iamd.MinValue.HasValue ? iamd.MinValue.Value.ToString(CultureInfo.InvariantCulture) : "N/A",
                                iamd.MaxValue.HasValue ? iamd.MaxValue.Value.ToString(CultureInfo.InvariantCulture) : "N/A"));
                        }
                        break;
                    case AttributeTypeCode.Lookup:
                        {
                            var lamd = (LookupAttributeMetadata)amd;

                            var format = lamd.Targets.Aggregate("Targets:", (current, entity) => current + ("\r\n" + entity));

                            sheet.Cells[x, y].Value = (format);
                        }
                        break;
                    case AttributeTypeCode.Memo:
                        {
                            var mamd = (MemoAttributeMetadata)amd;

                            sheet.Cells[x, y].Value = (string.Format(
                                "Format: {0}\r\nMax length: {1}",
                                mamd.Format.HasValue ? mamd.Format.Value.ToString() : "N/A",
                                mamd.MaxLength.HasValue ? mamd.MaxLength.Value.ToString(CultureInfo.InvariantCulture) : "N/A"));
                        }
                        break;
                    case AttributeTypeCode.Money:
                        {
                            var mamd = (MoneyAttributeMetadata)amd;

                            sheet.Cells[x, y].Value = (string.Format(
                                "Minimum value: {0}\r\nMaximum value: {1}\r\nPrecision: {2}",
                                mamd.MinValue.HasValue ? mamd.MinValue.Value.ToString(CultureInfo.InvariantCulture) : "N/A",
                                mamd.MaxValue.HasValue ? mamd.MaxValue.Value.ToString(CultureInfo.InvariantCulture) : "N/A",
                                mamd.Precision.HasValue ? mamd.Precision.Value.ToString(CultureInfo.InvariantCulture) : "N/A"));
                        }
                        break;
                    case AttributeTypeCode.Owner:
                        {
                            // Do nothing
                        }
                        break;
                    case AttributeTypeCode.PartyList:
                        {
                            // Do nothing
                        }
                        break;
                    case AttributeTypeCode.Picklist:
                        {
                            var pamd = (PicklistAttributeMetadata)amd;

                            string format = "Options:";

                            foreach (var omd in pamd.OptionSet.Options)
                            {
                                format += string.Format("\r\n{0}: {1}",
                                                        omd.Value,
                                                        omd.Label.LocalizedLabels.First(l => l.LanguageCode == _settings.DisplayNamesLangugageCode).Label);
                            }

                            format += string.Format("\r\nDefault: {0}", pamd.DefaultFormValue.HasValue ? pamd.DefaultFormValue.Value.ToString(CultureInfo.InvariantCulture) : "N/A");

                            sheet.Cells[x, y].Value = (format);
                        }
                        break;
                    case AttributeTypeCode.State:
                        {
                            var samd = (StateAttributeMetadata)amd;

                            string format = "States:";

                            foreach (var omd in samd.OptionSet.Options)
                            {
                                format += string.Format("\r\n{0}: {1}",
                                                        omd.Value,
                                                        omd.Label.LocalizedLabels.First(l => l.LanguageCode == _settings.DisplayNamesLangugageCode).Label);
                            }

                            sheet.Cells[x, y].Value = (format);
                        }
                        break;
                    case AttributeTypeCode.Status:
                        {
                            var samd = (StatusAttributeMetadata)amd;

                            string format = "States:";

                            foreach (OptionMetadata omd in samd.OptionSet.Options)
                            {
                                format += string.Format("\r\n{0}: {1}",
                                                        omd.Value,
                                                        omd.Label.LocalizedLabels.First(l => l.LanguageCode == _settings.DisplayNamesLangugageCode).Label);
                            }

                            sheet.Cells[x, y].Value = (format);
                        }
                        break;
                    case AttributeTypeCode.String:
                        {
                            var samd = (StringAttributeMetadata)amd;

                            sheet.Cells[x, y].Value = (string.Format(
                                "Format: {0}\r\nMax length: {1}",
                                samd.Format.HasValue ? samd.Format.Value.ToString() : "N/A",
                                samd.MaxLength.HasValue ? samd.MaxLength.Value.ToString(CultureInfo.InvariantCulture) : "N/A"));
                        }
                        break;
                    case AttributeTypeCode.Uniqueidentifier:
                        {
                            // Do Nothing
                        }
                        break;
                }
        }

        /// <summary>
        /// Adds row header for attribute list
        /// </summary>
        /// <param name="sheet">Worksheet where to write</param>
        /// <param name="x">Row number</param>
        /// <param name="y">Cell number</param>
        private void InsertAttributeHeader(ExcelWorksheet sheet, int x, int y)
        {
            // Write the header
            sheet.Cells[x, y].Value = ("Logical Name");
            y++;

            sheet.Cells[x, y].Value = ("Schema Name");
            y++;

            sheet.Cells[x, y].Value = ("Display Name");
            y++;

            sheet.Cells[x, y].Value = ("Type");
            y++;

            sheet.Cells[x, y].Value = ("Description");
            y++;

            sheet.Cells[x, y].Value = ("Custom Attribute");
            y++;

            if (_settings.AddRequiredLevelInformation)
            {
                sheet.Cells[x, y].Value = ("Required Level");
                y++;
            }

            if (_settings.AddValidForAdvancedFind)
            {
                sheet.Cells[x, y].Value = ("ValidFor AdvancedFind");
                y++;
            }

            if (_settings.AddAuditInformation)
            {
                sheet.Cells[x, y].Value = ("Audit Enabled");
                y++;
            }

            if (_settings.AddFieldSecureInformation)
            {
                sheet.Cells[x, y].Value = ("Secured");
                y++;
            }

            sheet.Cells[x, y].Value = ("Additional data");
            y++;

            for (int i = 0; i <= y; i++)
            {
                sheet.Cells[x, i].Style.FillPattern.SetSolid(Color.PowderBlue);
                sheet.Cells[x, i].Style.Font.Weight = ExcelFont.BoldWeight;
                sheet.Columns[i].AutoFit();
            }
        }

        /// <summary>
        /// Adds row header for attribute list
        /// </summary>
        /// <param name="sheet">Worksheet where to write</param>
        /// <param name="x">Row number</param>
        /// <param name="y">Cell number</param>
        private void InsertEntityHeader(ExcelWorksheet sheet, int x, int y)
        {
            // Write the header
            sheet.Cells[x, y].Value = ("Entity");
            y++;

            sheet.Cells[x, y].Value = ("Plural Display Name");
            y++;

            sheet.Cells[x, y].Value = ("Description");
            y++;

            sheet.Cells[x, y].Value = ("Schema Name");
            y++;

            sheet.Cells[x, y].Value = ("Logical Name");
            y++;

            sheet.Cells[x, y].Value = ("Object Type Code");
            y++;

            sheet.Cells[x, y].Value = ("Is Custom Entity");
            y++;

            sheet.Cells[x, y].Value = ("Ownership Type");
            y++;

            for (int i = 1; i < y; i++)
            {
                sheet.Cells[x, i].Style.FillPattern.SetSolid(Color.PowderBlue);
                sheet.Cells[x, i].Style.Font.Weight = ExcelFont.BoldWeight;
            }
        }

        public void AddEntityMetadataInLine(EntityMetadata emd, ExcelWorksheet sheet)
        {
            var y = 0;

            if (!_entitiesHeaderAdded)
            {
                _lineNumber += 2;
                InsertEntityHeader(sheet, _lineNumber, y);
                _entitiesHeaderAdded = true;
            }
            _lineNumber++;

             sheet.Cells[_lineNumber, y].Value = (emd.DisplayName.LocalizedLabels.Count == 0 ? emd.SchemaName : emd.DisplayName.LocalizedLabels.First(l => l.LanguageCode == _settings.DisplayNamesLangugageCode).Label);
            y++;

            sheet.Cells[_lineNumber, y].Value = (emd.DisplayCollectionName.LocalizedLabels.Count == 0 ? "N/A" : emd.DisplayCollectionName.LocalizedLabels.First(l => l.LanguageCode == _settings.DisplayNamesLangugageCode).Label);
            y++;

            sheet.Cells[_lineNumber, y].Value = (emd.Description.LocalizedLabels.Count == 0 ? "N/A" : emd.Description.LocalizedLabels.First(l => l.LanguageCode == _settings.DisplayNamesLangugageCode).Label);
            y++;

            sheet.Cells[_lineNumber, y].Value = (emd.SchemaName);
            y++;

            sheet.Cells[_lineNumber, y].Value = (emd.LogicalName);
            y++;

            if (emd.ObjectTypeCode != null) sheet.Cells[_lineNumber, y].Value = (emd.ObjectTypeCode.Value);
            y++;

            sheet.Cells[_lineNumber, y].Value = (emd.IsCustomEntity != null && emd.IsCustomEntity.Value);
            y++;

            if (emd.OwnershipType != null) sheet.Cells[_lineNumber, y].Value = (emd.OwnershipType.Value);
        }

        internal void Write(string message, ExcelWorksheet sheet, int x, int y)
        {
            sheet.Cells[x, y].Value = message;
        }

        #endregion Methods

    }
}
